import pandas as pd
import jieba
import jieba.analyse
from collections import Counter
import matplotlib.pyplot as plt
import seaborn as sns
from wordcloud import WordCloud
import re
import numpy as np

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号


def load_data(filepath):
    """加载数据"""
    try:
        df = pd.read_csv(filepath)
        print(f"成功读取 {len(df)} 条评论数据")
        return df
    except FileNotFoundError:
        print(f"错误：找不到文件 {filepath}")
        print("请确保文件存在，或者先运行爬虫程序生成数据文件")
        return None


def clean_text(text):
    """清洗文本"""
    if pd.isna(text):
        return ""
    # 去除特殊字符和标点
    text = re.sub(r'[^\w\s]', '', str(text))
    # 去除数字
    text = re.sub(r'\d+', '', text)
    return text.strip()


def convert_rating(rating):
    """转换评分为数值类型"""
    if isinstance(rating, (int, float)):
        return rating
    elif isinstance(rating, str):
        # 处理各种评分格式
        if rating.isdigit():  # "5", "4" 等
            return int(rating)
        elif rating == '无评分':  # 处理无评分情况
            return 0
        else:
            return 0
    else:
        return 0


def analyze_sentiment_from_rating(rating):
    """根据评分判断情感"""
    rating_num = convert_rating(rating)
    if rating_num >= 4:
        return 'positive'
    elif rating_num == 3:
        return 'neutral'
    elif rating_num > 0:
        return 'negative'
    else:
        return 'unknown'


def analyze_comments():
    """分析评论数据"""

    # 读取数据
    df = load_data('douban_movie_comments.csv')
    if df is None:
        return

    # 数据预览
    print("\n数据预览:")
    print(df.head())
    print(f"\n数据形状: {df.shape}")
    print(f"列名: {df.columns.tolist()}")

    # 检查缺失值
    print(f"\n缺失值统计:")
    print(df.isnull().sum())

    # 检查评分列的数据类型和唯一值
    print(f"\n评分列的唯一值: {df['评分'].unique()}")
    print(f"评分列的数据类型: {df['评分'].dtype}")

    # 清洗评论内容
    print("\n正在清洗评论内容...")
    df['清洗后评论'] = df['评论内容'].apply(clean_text)

    # 评分分析
    print("\n=== 评分分析 ===")
    df['数值评分'] = df['评分'].apply(convert_rating)

    # 情感分析（基于评分）
    df['sentiment'] = df['评分'].apply(analyze_sentiment_from_rating)

    rating_stats = df['数值评分'].describe()
    print(f"评分统计:\n{rating_stats}")

    # 情感分布
    sentiment_counts = df['sentiment'].value_counts()
    print(f"\n情感分布:")
    print(sentiment_counts)

    # 绘制评分分布
    plt.figure(figsize=(12, 5))

    plt.subplot(1, 2, 1)
    rating_counts = df[df['数值评分'] > 0]['数值评分'].value_counts().sort_index()
    plt.bar(rating_counts.index, rating_counts.values, color='skyblue')
    plt.title('电影评分分布')
    plt.xlabel('评分')
    plt.ylabel('评论数量')

    plt.subplot(1, 2, 2)
    colors = {'positive': 'green', 'neutral': 'orange', 'negative': 'red', 'unknown': 'gray'}
    sentiment_colors = [colors.get(sent, 'gray') for sent in sentiment_counts.index]
    plt.pie(sentiment_counts.values, labels=sentiment_counts.index, autopct='%1.1f%%', colors=sentiment_colors)
    plt.title('情感分布')

    plt.tight_layout()
    plt.savefig('评分分布.png', dpi=300, bbox_inches='tight')
    plt.show()

    # 有用数分析
    print("\n=== 有用数分析 ===")
    df['有用数'] = pd.to_numeric(df['有用数'], errors='coerce').fillna(0)
    useful_stats = df['有用数'].describe()
    print(f"有用数统计:\n{useful_stats}")

    # 评论长度分析
    print("\n=== 评论长度分析 ===")
    df['评论长度'] = df['清洗后评论'].str.len()
    length_stats = df['评论长度'].describe()
    print(f"评论长度统计:\n{length_stats}")

    # 绘制评论长度分布
    plt.figure(figsize=(10, 6))
    plt.hist(df['评论长度'], bins=50, alpha=0.7, edgecolor='black', color='lightcoral')
    plt.title('评论长度分布')
    plt.xlabel('评论长度（字符数）')
    plt.ylabel('频次')
    plt.savefig('评论长度分布.png', dpi=300, bbox_inches='tight')
    plt.show()

    # 时间分析
    print("\n=== 时间分析 ===")
    df['评论时间'] = pd.to_datetime(df['评论时间'], errors='coerce')
    df = df.dropna(subset=['评论时间'])

    # 按月份统计评论数量
    df['评论月份'] = df['评论时间'].dt.to_period('M')
    monthly_comments = df['评论月份'].value_counts().sort_index()

    plt.figure(figsize=(12, 6))
    monthly_comments.plot(kind='line', marker='o', color='purple')
    plt.title('月度评论数量趋势')
    plt.xlabel('月份')
    plt.ylabel('评论数量')
    plt.xticks(rotation=45)
    plt.grid(True, alpha=0.3)
    plt.savefig('评论趋势.png', dpi=300, bbox_inches='tight')
    plt.show()

    # 关键词提取
    print("\n=== 关键词分析 ===")
    all_comments = ' '.join(df['清洗后评论'].dropna().tolist())

    # 使用jieba提取关键词
    keywords = jieba.analyse.extract_tags(all_comments, topK=20, withWeight=True)
    print("Top 20 关键词:")
    for word, weight in keywords:
        print(f"{word}: {weight:.4f}")

    # 绘制关键词条形图
    plt.figure(figsize=(12, 8))
    words = [word for word, _ in keywords]
    weights = [weight for _, weight in keywords]
    plt.barh(words, weights, color='lightgreen')
    plt.title('评论关键词权重')
    plt.xlabel('权重')
    plt.gca().invert_yaxis()
    plt.tight_layout()
    plt.savefig('关键词权重.png', dpi=300, bbox_inches='tight')
    plt.show()

    # 生成词云
    print("\n正在生成词云...")
    try:
        wordcloud = WordCloud(
            width=800,
            height=400,
            background_color='white',
            font_path='simhei.ttf',
            max_words=100,
            colormap='viridis'
        ).generate(all_comments)

        plt.figure(figsize=(10, 5))
        plt.imshow(wordcloud, interpolation='bilinear')
        plt.axis('off')
        plt.title('评论关键词词云')
        plt.savefig('词云.png', dpi=300, bbox_inches='tight')
        plt.show()
        print("词云已保存为 '词云.png'")
    except Exception as e:
        print(f"生成词云时出错: {e}")
        print("尝试使用文本关键词分析代替...")

    # 用户活跃度分析
    print("\n=== 用户活跃度分析 ===")
    user_activity = df['用户名'].value_counts()
    print(f"总用户数: {len(user_activity)}")
    print(f"最活跃的前10名用户:")
    print(user_activity.head(10))

    # 保存分析结果
    print("\n正在保存分析结果...")

    # 保存清洗后的数据
    df.to_csv('清洗后评论数据.csv', index=False, encoding='utf-8-sig')

    # 生成分析报告
    with open('分析报告.txt', 'w', encoding='utf-8') as f:
        f.write("豆瓣电影评论分析报告\n")
        f.write("=" * 50 + "\n")
        f.write(f"分析时间: {pd.Timestamp.now()}\n")
        f.write(f"总评论数: {len(df)}\n")
        f.write(f"总用户数: {len(user_activity)}\n")
        f.write(f"平均评分: {rating_stats['mean']:.2f}\n")
        f.write(f"平均评论长度: {length_stats['mean']:.2f} 字符\n")
        f.write(f"情感分布 - 正面: {sentiment_counts.get('positive', 0)}, ")
        f.write(f"中性: {sentiment_counts.get('neutral', 0)}, ")
        f.write(f"负面: {sentiment_counts.get('negative', 0)}\n")
        f.write("\nTop 20 关键词:\n")
        for word, weight in keywords:
            f.write(f"{word}: {weight:.4f}\n")

    print("分析完成！")
    print("生成的文件:")
    print("- 清洗后评论数据.csv")
    print("- 评分分布.png")
    print("- 评论长度分布.png")
    print("- 评论趋势.png")
    print("- 关键词权重.png")
    print("- 词云.png")
    print("- 分析报告.txt")


if __name__ == '__main__':
    analyze_comments()